﻿using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace Kitty
{
    public partial class Main : CombatRoutine
    {
        internal readonly Version Version = new Version(1, 0, 0);
        public override string Name { get { return "Pasterke's Feral Combat Routine"; } }
        public override WoWClass Class { get { return WoWClass.Druid; } }
        public LocalPlayer Me { get { return StyxWoW.Me; } }

        private Composite _preCombatBuffs, _combatBuffs, _Heal, _Combat, _Pull, _pullBuffs;
        public override Composite PreCombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _preCombatBuffs; } }
        public override Composite CombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _combatBuffs; } }
        public override Composite HealBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Heal; } }
        public override Composite CombatBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Combat; } }
        public override Composite PullBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Pull; } }
        public override Composite PullBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _pullBuffs; } }
        private Random rnd = new Random();
        public string usedBot { get { return BotManager.Current.Name; } }
        public override bool WantButton { get { return true; } }


        public override void OnButtonPress()
        {
            Form2 ConfigForm = new Form2();
            ConfigForm.ShowDialog();
        }

        #region pulse
        public override void Pulse()
        {
            try
            {
                if (Me.Combat && targetCheckTimer.IsRunning)
                {
                    targetCheckTimer.Reset();
                    return;
                }
                if (gotTarget
                    && !targetCheckTimer.IsRunning)
                {
                    targetCheckTimer.Restart();
                    return;
                }
                if (Me.Combat
                    && !QuestOrGrind
                    && Me.CurrentTarget.IsFriendly)
                {
                    Me.ClearTarget();
                }
                if (gotTarget
                    && !Me.Combat
                    && targetCheckTimer.ElapsedMilliseconds >= 40000)
                {
                    LogMsg("Take too long to engage Combat, Blacklisting " + Me.CurrentTarget.Name + " for 3 min", 0);
                    Blacklist.Add(Me.CurrentTarget.Guid, TimeSpan.FromMinutes(3));
                    Me.ClearTarget();
                    targetCheckTimer.Reset();
                    return;
                }
                if (QuestOrGrind
                    && Me.Combat
                    && Me.Mounted
                    && !Me.IsFlying
                    && Me.Shapeshift != ShapeshiftForm.FlightForm)
                {
                    Lua.DoString("Dismount()");
                    return;
                }
                if (Me.IsDead
                    && QuestOrGrind)
                {
                    int Delay = rnd.Next(2000, 7000);
                    Thread.Sleep(Delay);
                    Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                    return;

                }
            }
            catch { }
        }
        #endregion pulse

        #region Initialize
        public override void Initialize()
        {
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            Lua.Events.AttachEvent("UI_ERROR_MESSAGE", CombatLogErrorHandler);

            _preCombatBuffs = createPreCombatBuffs();
            _combatBuffs = createCombatBuffs();
            _Heal = createBuffs();
            _Combat = createCombat();
            _Pull = createPull();
            _pullBuffs = createPullBuffs();

        }
        #endregion

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
            Lua.Events.DetachEvent("UI_ERROR_MESSAGE", CombatLogErrorHandler);
        }

        #region rest
        public override bool NeedRest
        {
            get
            {
                if (SpellManager.HasSpell("Healing Touch")
                    && LastSpell != "Healing Touch"
                    && Me.HealthPercent <= CRSettings.myPrefs.HealingTouchOoc)
                {
                    return true;
                }
                if (SpellManager.HasSpell("Rejuvenation")
                    && LastSpell != "Rejuvenation"
                    && Me.HealthPercent <= CRSettings.myPrefs.RejuOoc
                    && Me.HealthPercent > CRSettings.myPrefs.HealingTouchOoc)
                {
                    return true;
                }
                if (Me.HealthPercent <= CRSettings.myPrefs.food)
                {
                    return true;
                }
                return false;
            }
        }

        public override void Rest()
        {
            if (SpellManager.HasSpell("Rejuvenation")
                && !Me.Mounted
                && !Me.IsFlying
                && Me.HealthPercent <= CRSettings.myPrefs.RejuOoc
                && !Me.IsDead
                && !Me.IsGhost
                && !buffExists("Rejuvenation", Me)
                && LastSpell != "Rejuvenation")
            {
                SpellManager.Cast("Rejuvenation", Me);
            }
            if (SpellManager.HasSpell("Healing Touch")
                && !Me.IsFlying
                && !Me.Mounted
                && Me.HealthPercent <= CRSettings.myPrefs.HealingTouchOoc
                && !Me.IsDead
                && !Me.IsGhost
                && LastSpell != "Healing Touch")
            {
                SpellManager.Cast("Healing Touch", Me);
            }
            if ((Me.HealthPercent <= CRSettings.myPrefs.food || (!SpellManager.HasSpell("Healing Touch") && Me.HealthPercent <= CRSettings.myPrefs.HealingTouchOoc))
                && !Me.IsDead
                && !Me.IsGhost
                && !Me.IsSwimming
                && !Me.Mounted
                && !Me.IsFlying)
            {
                Styx.CommonBot.Rest.Feed();
            }
        }

        #endregion rest

        #region createPreCombatBuffs
        Composite createPreCombatBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => PauseAoe, crPaused()),
                CastBuff("Mark of the Wild", "Mark of the Wild", 2, ret => SpellManager.HasSpell("Mark of the Wild")
                    && !buffExists("Mark of the Wild", Me)
                    && !buffExists("Legacy of the Emperor", Me)
                    && !buffExists("Blessing of Kings", Me)
                    && !buffExists("Embrace of the Shale Spider", Me)
                    && ((CRSettings.myPrefs.motw == CRSettings.CastMotW.NotInParty && !Me.GroupInfo.IsInParty)
                    || (CRSettings.myPrefs.motw == CRSettings.CastMotW.AlwaysButNotInCombat && !Me.Combat)
                    || CRSettings.myPrefs.motw == CRSettings.CastMotW.Always)
                    && Me.Shapeshift != ShapeshiftForm.FlightForm
                    && !Me.Mounted
                    && !Me.IsFlying
                    && LastSpell != "Mark of the Wild"),
                CastBuff("Aquatic Form", "Aquatic Form", 2, ret => SpellManager.HasSpell("Aquatic Form")
                    && CRSettings.myPrefs.autoAqua
                    && Me.Shapeshift != ShapeshiftForm.Aqua
                    && !Me.Combat
                    && Me.IsSwimming
                    && !Me.Mounted
                    && !buffExists("Prowl", Me)),
                new Decorator(ret => CRSettings.myPrefs.AlchemyFlask
                    && !buffExists("Enhanced Agility", Me)
                    && !buffExists("Visions of Insanity", Me)
                    && !buffExists("Flask of Spring Blossoms", Me), useAlchemyFlask())
                );
        }
        #endregion createPreCombatBuffs

        #region CombatBuffs
        Composite createCombatBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused || ((Me.IsFlying || Me.Mounted || Me.Shapeshift == ShapeshiftForm.FlightForm) && !QuestOrGrind), crPaused()),
                CastBuff("Mark of the Wild", "Mark of the Wild", 2, ret => SpellManager.HasSpell("Mark of the Wild")
                    && !buffExists("Mark of the Wild", Me)
                    && !buffExists("Legacy of the Emperor", Me)
                    && !buffExists("Blessing of Kings", Me)
                    && !buffExists("Embrace of the Shale Spider", Me)
                    && ((CRSettings.myPrefs.motw == CRSettings.CastMotW.NotInParty && !Me.GroupInfo.IsInParty)
                    || (CRSettings.myPrefs.motw == CRSettings.CastMotW.AlwaysButNotInCombat && !Me.Combat)
                    || CRSettings.myPrefs.motw == CRSettings.CastMotW.Always)
                    && Me.Shapeshift != ShapeshiftForm.FlightForm
                    && !Me.Mounted
                    && !Me.IsFlying
                    && LastSpell != "Mark of the Wild"),
                new Decorator(ret => gotTarget
                    && Me.HealthPercent <= CRSettings.myPrefs.healthstonepercent,
                    useHealthStone()),
                new Decorator(ret => CRSettings.myPrefs.AlchemyFlask
                    && !buffExists("Enhanced Agility", Me)
                    && !buffExists("Visions of Insanity", Me)
                    && !buffExists("Flask of Spring Blossoms", Me), useAlchemyFlask()),
                new Decorator(ret => ((CRSettings.myPrefs.useFlask == CRSettings.WhenToUseFlask.AllRaids && Me.GroupInfo.IsInRaid)
                    || (CRSettings.myPrefs.useFlask == CRSettings.WhenToUseFlask.Instances && Me.IsInInstance)
                    || (CRSettings.myPrefs.useFlask == CRSettings.WhenToUseFlask.RaidsButNotLFR && Me.GroupInfo.IsInRaid && !Me.GroupInfo.IsInLfgParty))
                    && !buffExists("Flask of Spring Blossoms", Me),
                    useAgiFlask()),
                CastBuff("Might of Ursoc", "Might of Ursoc", 2, ret => gotTarget
                    && SpellManager.HasSpell("Might of Ursoc")
                    && !spellOnCooldown("Might of Ursoc")
                    && Me.HealthPercent <= CRSettings.myPrefs.ursoc),
                Cast("Bone Shield", "Bone Shield", 2, ret => gotTarget
                    && SpellManager.HasSpell("Bone Shield")
                    && !spellOnCooldown("Bone Shield")
                    && !buffExists("Bone Shield", Me)),
                CastBuff("Cenarion Ward", "Cenarion Ward", 2, ret => gotTarget
                    && SpellManager.HasSpell("Cenarion Ward")
                    && !spellOnCooldown("Cenarion Ward")
                    && Me.HealthPercent <= CRSettings.myPrefs.CenarionWard
                    && LastSpell != "Cenarion Ward"),
                CastBuff("Barkskin", "Barkskin", 2, ret => gotTarget
                    && SpellManager.HasSpell("Barkskin")
                    && !spellOnCooldown("Barkskin")
                    && Me.HealthPercent <= CRSettings.myPrefs.Barkskin
                    && LastSpell != "Barkskin"),
                CastBuff("Survival Intstincts", "Survival Instincts", 2, ret => gotTarget
                    && SpellManager.HasSpell("Survival Instincts")
                    && !spellOnCooldown("Survival Instincts")
                    && Me.HealthPercent <= CRSettings.myPrefs.survivalInstincts
                    && LastSpell != "Survival Instincts"),
                CastBuff("Frenzied Regeneration", "Frenzied Regeneration", 2, ret => gotTarget
                    && SpellManager.HasSpell("Frenzied Regeneration")
                    && Me.Shapeshift == ShapeshiftForm.Bear
                    && !spellOnCooldown("Frenzied Regeneration")
                    && Me.HealthPercent <= CRSettings.myPrefs.frenzied
                    && Me.RagePercent >= 70
                    && LastSpell != "Frenzied Regeneration"),
                CastBuff("Renewal", "Renewal", 2, ret => gotTarget
                    && SpellManager.HasSpell("Renewal")
                    && !spellOnCooldown("Renewal")
                    && Me.HealthPercent <= CRSettings.myPrefs.renewal
                    && LastSpell != "Renewal"),
                Cast("Feral Spirit", "Feral Spirit", 2, ret => gotTarget
                    && SpellManager.HasSpell("Feral Spirit")
                    && !spellOnCooldown("Feral Spirit")
                    && (CRSettings.myPrefs.feralSpirit == CRSettings.CooldownPrefs.OnCoolDown
                    || (CRSettings.myPrefs.feralSpirit == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget)))
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && LastSpell != "Feral Spirit"),
                new Decorator(ret => gotTarget && MeRooted(), MeIsRooted()),
                Cast("Nature's Vigil", "Nature's Vigil", 2, ret => gotTarget
                    && SpellManager.HasSpell("Nature's Vigil")
                    && !spellOnCooldown("Nature's Vigil")
                    && (CRSettings.myPrefs.natureVigil == CRSettings.CooldownPrefs.OnCoolDown
                    || (CRSettings.myPrefs.natureVigil == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget)))
                    && LastSpell != "Nature's Vigil")
                );
        }
        #endregion CombatBuffs

        #region Pull buffs
        Composite createPullBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),
                CastBuff("Cat Form", "Cat Form", 2, ret => gotTarget
                    && Me.Specialization == WoWSpec.DruidFeral
                    && Me.Shapeshift != ShapeshiftForm.Cat
                    && !buffExists("Might of Ursoc", Me)
                    && !SwitchBearForm),
                CastBuff("Bear Form", "Bear Form", 2, ret => gotTarget
                    && Me.Shapeshift != ShapeshiftForm.Bear
                    && Me.Specialization == WoWSpec.DruidGuardian
                    || (Me.Specialization == WoWSpec.DruidFeral && Me.Shapeshift != ShapeshiftForm.Bear
                    && (buffExists("Might of Ursoc", Me)
                    || SwitchBearForm))),
                Cast("Prowl", "Prowl", 2, ret => gotTarget
                    && SpellManager.HasSpell("Pounce")
                    && CRSettings.myPrefs.spellToPull == CRSettings.pullSpell.ProwlWithPounce
                    && Me.Shapeshift == ShapeshiftForm.Cat
                    && !spellOnCooldown("Prowl")
                    && !buffExists("Prowl", Me)
                    && LastSpell != "Prowl")
             );
        }
        #endregion pull buffs

        #region Pull
        Composite createPull()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),
                new Decorator(ret => Me.CurrentTarget == null || Me.CurrentTarget.IsDead || Me.CurrentTarget.IsFriendly, ensureTarget()),
                new Decorator(ret => gotTarget, moveControlls(pullRange)),
                new Decorator(ret => gotTarget, PullNow())

            );
        }
        #endregion

        #region Combat
        Composite createCombat()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),
                new Decorator(ret => (Me.CurrentTarget == null || Me.CurrentTarget.IsDead || Me.CurrentTarget.IsFriendly) && CRSettings.myPrefs.Targeting, ensureTarget()),
                new Decorator(ret => gotTarget && CRSettings.myPrefs.Movement, moveControlls(3.5f)),
                new Decorator(ret => gotTarget && !SpellManager.HasSpell("Cat Form"), LowieRotation()),
                new Decorator(ret => gotTarget && Me.Specialization == WoWSpec.DruidGuardian, GuardianRotation()),
                new Decorator(ret => Me.Specialization == WoWSpec.DruidFeral
                    && (SwitchBearForm || buffExists("Might of Ursoc", Me) || (addCount >= CRSettings.myPrefs.SwitchBear && !Me.GroupInfo.IsInRaid && !Me.IsInInstance))
                    && !PauseAoe,
                    BearRotation()),
                new Decorator(ret => gotTarget
                    && addCount >= CRSettings.myPrefs.StartCatAoe
                    && SpellManager.HasSpell("Swipe")
                    && !SwitchBearForm
                    && !buffExists("Might of Ursoc", Me), AoeRotation()),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Cat Form")
                    && !SwitchBearForm
                    && !buffExists("Might of Ursoc", Me), CatRotation())
                );
        }
        Composite CatRotation()
        {
            return new PrioritySelector(
                CatForm(),
                createMoveInRange(3.5f),
                createLignOfSight(),
                createStopMove(3.5f),
                createFacing(),
                FerociousBite(),
                Rake(),
                Rip(),
                Thrash(),
                SavageRoar(),
                WildCharge(),
                PredatoryHeal(),
                SkullBash(),
                MightyBash(),
                TigersFury(),
                Faerie(),
                Berserk(),
                Berserking(),
                Trinket1(),
                Trinket2(),
                Gloves(),
                StatsPotion(),
                Incarnation(),
                Ravage(),
                Shred(),
                Lifeblood(),
                Mangle()
                );
        }

        Composite AoeRotation()
        {
            return new PrioritySelector(
                CatForm(),
                createMoveInRange(3.5f),
                createLignOfSight(),
                createStopMove(3.5f),
                createFacing(),
                PredatoryHeal(),
                TigersFury(),
                SavageRoar(),
                Thrash(),
                Swipe(),
                Lifeblood()
                );
        }
        Composite BearRotation()
        {
            return new PrioritySelector(
                BearForm(),
                createMoveInRange(3.5f),
                createLignOfSight(),
                createStopMove(3.5f),
                createFacing(),
                Maul(),
                MangleBear(),
                ThrashBear(),
                SwipeBear(),
                Lacerate()
                );
        }
        Composite LowieRotation()
        {
            return new PrioritySelector(
                createMoveInRange(35),
                createLignOfSight(),
                createStopMove(35),
                createFacing(),
                Cast("Moonfire", "Moonfire", 1, ret => gotTarget
                    && SpellManager.HasSpell("Moonfire")
                    && !debuffExists("Moonfire", Me.CurrentTarget)),
                Cast("Wrath", "Wrath", 1, ret => gotTarget
                    && SpellManager.HasSpell("Wrath"))

                );
        }
        Composite GuardianRotation()
        {
            return new PrioritySelector(

                );
        }
        #endregion


        private Composite autoAttack()
        {
            return new PrioritySelector(
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking && Me.CurrentTarget.IsWithinMeleeRange,
                        new Action(ret =>
                        {
                            Lua.DoString("StartAttack()");
                            return RunStatus.Failure;
                        }))
                    );
        }

        Composite crPaused()
        {
            return new Action(ret =>
            {
                return;
            });
        }
    }
}
